package ca.etsmtl.log430.lab1;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Main class for assignment 1 for LOG430, Architecture logicielle.
 * 
 * <pre>
 * <b>Pseudo Code:</b>
 * 
 *   Instantiate lists
 *   do until done
 *     Present Menu
 *     if user choice = 1 then list resources
 *     if user choice = 2 then list projects
 *     if user choice = 3 then
 *        list resources
 *        ask user to select a resource (by ID)
 *        list projects assigned to that resource
 *     endif
 *     if user choice = 4 then
 *        list projects
 *        ask user to select a project (by ID)
 *        list resources assigned to that project
 *     endif
 *     if user choice = 5 then
 *        list resources
 *        ask user to select a resource (by ID)
 *        list projects
 *        ask user to select a project (by ID)
 *        assign project to resource (and vice versa)
 *     endif
 *     if user choice = x then you are done
 *   end do
 * </pre>
 * 
 * @author A.J. Lattanze, CMU
 * @version 1.5, 2013-Sep-13
 */

/*
 * Modification Log
 * **************************************************************************
 * v1.5, R. Champagne, 2013-Sep-13 - Various refactorings for new lab.
 * 
 * v1.4, R. Champagne, 2012-May-31 - Various refactorings for new lab.
 * 
 * v1.3, R. Champagne, 2012-Feb-02 - Various refactorings for new lab.
 * 
 * v1.2, 2011-Feb-02, R. Champagne - Various refactorings, javadoc comments.
 * 
 * v1.1, 2002-May-21, R. Champagne - Adapted for use at ETS.
 * 
 * v1.0, 12/29/99, A.J. Lattanze - Original version.
 * **************************************************************************
 */

public class ResourceAssignment {

	public static void main(String argv[]) {

		if (argv.length != 2) {
			System.out.println("\n\nIncorrect number of input parameters -"
					+ " correct usage:");
			System.out.println("\njava ResourceAssignment <project file name>"
					+ " <resource file name>");
		} else {

			// Declarations:

			boolean done; // Loop invariant
			char userChoice; // User's menu choice
			Project project = null; // A project object
			Resource resource = null; // A resource object

			// Instantiates a menu object
			Menus menu = new Menus();

			// Instantiates a display object
			Displays display = new Displays();

			/*
			 * The following instantiations create a list of projects and
			 * resources. The pathname for the file containing course information
			 * is passed to the main program on the command line as the first
			 * argument (argv[0]). The pathname for the file containing resource
			 * information is passed to the main program on the command line as
			 * the second argument (argv[1]). An example resources file and projects
			 * file is provided as resources.txt and projects.txt
			 */

			ProjectReader projectList = new ProjectReader(argv[0]);
			ResourceReader resourceList = new ResourceReader(argv[1]);

			if ((projectList.getListOfProjects() == null)
					|| (resourceList.getListOfResources() == null)) {
				System.out
				.println("\n\n *** The projects list and/or the resources"
						+ " list was not initialized ***");
				done = true;
			} else {
				done = false;
			} // if

			while (!done) {

				userChoice = menu.mainMenu();
				switch (userChoice) {

				case '1':

					display.displayResourceList(resourceList.getListOfResources());
					break;

				case '2':

					display.displayProjectList(projectList.getListOfProjects());
					break;

				case '3':

					display.displayResourceList(resourceList.getListOfResources());
					resource = menu.pickResource(resourceList.getListOfResources());
					if (resource != null) {
						display.displayProjectsAssignedToResource(resource);
					} // if
					break;

				case '4':
					//Done - SP Therriault 2013-09-23
					display.displayResourceList(resourceList.getListOfResources());
					resource = menu.pickResource(resourceList.getListOfResources());

					if(resource != null)
						display.displayProjectsPreviouslyAssignedToResource(resource, projectList.getListOfProjects());

					break;

				case '5':

					display.displayProjectList(projectList.getListOfProjects());
					project = menu.pickProject(projectList.getListOfProjects());

					if (project != null) {
						display.displayResourcesAssignedToProject(project);
					} // if
					break;

				/**
				 * Case list that shows what are the roles that are assinged to the projects
				 * depending on the current and previous ProjectList
				 * 
				 * The case will aggregate all the different ANA, PRG, DES and TST roles
				 * In the case there are roles added, it will be necessary to hard code it within
				 * this method.
				 * 
				 */
				case '6':
					display.displayProjectList(projectList.getListOfProjects());
					project = menu.pickProject(projectList.getListOfProjects()); 

					int ANA=0,DES=0,PRG=0,TST=0; 
					boolean fini = false;

					project.getResourcesAssigned().goToFrontOfList();

					//Liste des project qui sont assigner presentement (dyan)	
					while (!fini) {
						resource = project.getResourcesAssigned().getNextResource();

						if (resource == null) {
							fini = true;
						} else { 
							String role=resource.getRole(); 

							if (role.equals("ANA")) 
								ANA++; 
							else if (role.equals("PRG")) 
								PRG++; 
							else if (role.equals("DES")) 
								DES++; 
							else if (role.equals("TST")) 
								TST++;
						} // if

					} // while
					
					System.out.println("");
					System.out.println("Pendant l'execution courante, \n " +
							"Dans le projet : " + project.getID() + "\n\t"
							+ ANA + " Analystes \n\t"
							+ PRG + " Programmeurs \n\t"
							+ DES + " Concepteurs \n\t"
							+ TST + " Testeurs");
					//Pendant l execution courante fini=false; 
					//Reinitialisation des parametres DES=0; TST=0; PRG=0; ANA=0; project.getResourcesAssigned().goToFrontOfList();

					System.out.println("");
					System.out.println("");
					
					//Liste des project qui sont deja assigner	
					resourceList.getListOfResources().goToFrontOfList();
					ResourceList listR = resourceList.getListOfResources();
					
					ANA=0;
					DES=0;
					PRG=0;
					TST=0; 
					
					Resource resource1 = listR.getNextResource();
					
					
					while (resource1 != null) {
						
						boolean pIsPresent = resource1.getPreviouslyAssignedProjectList().findProject(project);
						if (pIsPresent) {
							String role=resource1.getRole(); 
							
							if (role.equals("ANA")) 
								ANA++; 
							else if (role.equals("PRG")) 
								PRG++; 
							else if (role.equals("DES")) 
								DES++; 
							else if (role.equals("TST")) 
								TST++;
						}
						resource1 = listR.getNextResource();
					} // while

					System.out.println("");
					System.out.println("Avant l'execution courante, \n " +
							"Dans le projet : " + project.getID() + "\n\t"
							+ ANA + " Analystes \n\t"
							+ PRG + " Programmeurs \n\t"
							+ DES + " Concepteurs \n\t"
							+ TST + " Testeurs");
					
					System.out.println("");
					System.out.println("");
					System.out.println("Sa date de debut et de fin sont: "+ project.getStartDate()+" --- "+project.getEndDate());
					
					
					break;
					/**
					 * Case where the list will display all the available list and as well resources
					 * It will aswell determine if there is any error within the selection to determine
					 * if a resource is overloaded by time or priority to be able to be assign to the specified
					 * project. 
					 * 	Priority
					 * 		H : High 	----	100%
					 * 		M : Medium 	----	50%
					 * 		L : Low 	----	25%
					 * 
					 * 
					 */
				case '7':

					display.displayResourceList(resourceList.getListOfResources());
					resource = menu.pickResource(resourceList.getListOfResources());

					if (resource != null) {
						display.displayProjectList(projectList.getListOfProjects());
						project = menu.pickProject(projectList.getListOfProjects());

						try{
							if (project != null) {
								
								updateProjectList(resource, projectList.getListOfProjects());
								
								if (checkDateConflict(project, resource)){
									project.assignResource(resource);
									resource.assignProject(project);
								}else{
									throw new Exception();

								}

							} // if
						}catch(Exception e)
						{
							String message = e.getMessage() != null ? e.getMessage() : "Error - Assigning project to overloaded resource";
							//System.out.println("Error - Assigning project to overloaded resource");
							System.out.println(message);
							project = null;
						};
					} // if

					break;

				case 'X':

				case 'x':
					done = true;
				} // switch
			} // while
		} // if
	} // main

	/**
	 * Methods that allows to update the previous list of projects 
	 * @param resource
	 * @param pList
	 */
	public static void updateProjectList(Resource resource, ProjectList pList){
		
		resource.getPreviouslyAssignedProjectList().goToFrontOfList();
		
		Project project = resource.getPreviouslyAssignedProjectList().getNextProject();
		
		while(project != null){
			Project tmp = pList.findProjectByID(project.getID());
			
			if (tmp != null){
				project.setProjectName(tmp.getProjectName());
				project.setStartDate(tmp.getStartDate());
				project.setEndDate(tmp.getEndDate());
				project.setPriority(tmp.getPriority());
			}
			project = resource.getPreviouslyAssignedProjectList().getNextProject();
		}
	}
	
	/**
	 * CheckDateConflict allows the user to determine with a project and a resource if there is any conflicts
	 * either with dates or priority. The method will return a boolean indicating if there is a one or not. 
	 * In the case there is a error message will be shown to the console indicating what is wrong.
	 * 
	 * @param project
	 * @param resource
	 * @return
	 * @throws Exception
	 */
	public static boolean checkDateConflict(Project project,Resource resource) throws Exception{

		ProjectList pListCurrent = new ProjectList();
		ProjectList pListPrevious = new ProjectList();
		ProjectList pNewCurrentList = new ProjectList();


		resource.getPreviouslyAssignedProjectList().goToFrontOfList();
		resource.getProjectsAssigned().goToFrontOfList();

		pListCurrent = resource.getProjectsAssigned();
		pListPrevious = resource.getPreviouslyAssignedProjectList();

		Project p = resource.getPreviouslyAssignedProjectList().getNextProject();
		Project q = resource.getProjectsAssigned().getNextProject();

		//Current assigned projects
		while (q != null)
		{
			pNewCurrentList.addProject(q);
			q = pListCurrent.getNextProject();
		}

		//Previously assigned projects
		while (p != null)
		{	
			pNewCurrentList.addProject(p);
			p = pListPrevious.getNextProject();
		}

		pNewCurrentList.goToFrontOfList();
		Project r = pNewCurrentList.getNextProject();
		int cpt = 0;

		while(r != null)
		{
			//(StartA <= EndB) and (EndA >= StartB)
			if (!project.getID().equals(r.getID())){
				if (sToDateConv(r.getStartDate()).before(sToDateConv(project.getEndDate())) && sToDateConv(r.getEndDate()).after(sToDateConv(project.getStartDate())))
				{
					if(r.getPriority().equals("H"))
					{
						cpt += 100;
						//throw new Exception("Project overlap already a High Priority Project");
					}
					else if (r.getPriority().equals("L"))
					{
						cpt += 25;
					}
					else if (r.getPriority().equals("M"))
					{
						cpt += 50;
					}
					else 
					{
						throw new Exception("Error in Priority case !!!!! ");
					}
				}
			}else{
				throw new Exception("Project already assigned");
			}	
			r = pNewCurrentList.getNextProject();
		} 
		int projectprio = 0;
		if (project.getPriority().equals("H"))
			projectprio=100;
		else if(project.getPriority().equals("L"))
			projectprio=25;
		else if(project.getPriority().equals("M"))
			projectprio=50;

		if (cpt + projectprio > 100)
		{
			return false;
		}else{
			return true;
		}
	}
	
	/**
	 * sToDateConv allows the user to transform a string to a formated one and return an Object Date
	 * This allows to manipulate easier the date instance to make different calculation to validate if
	 * ranges of date conincide or are out of bound.
	 * 
	 * @param stringDate
	 * @return
	 */
	public static Date sToDateConv(String stringDate){

		DateFormat formatter;
		Date date = new Date();
		formatter = new SimpleDateFormat("yyyy-MM-dd");
		try {
			date = (Date) formatter.parse(stringDate);
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return date;
	}
} // Class